package com.recharge.job;

import com.alibaba.fastjson.JSON;
import com.recharge.AsyncTaskService;
import com.recharge.OrderService;
import com.recharge.domain.*;
import com.recharge.mapper.*;
import com.recharge.sup.AbsSupChargeService;
import com.recharge.utils.OrderStatus;
import com.recharge.utils.ProcessResult;
import com.recharge.utils.ValueConvertUtils;
import com.sun.org.apache.bcel.internal.generic.IF_ACMPEQ;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.hibernate.criterion.Order;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.*;

/**
 * Created by qi.cao on 2016/5/17.
 */
@Service
public class GetOrderService {

    private Logger logger = LoggerFactory.getLogger(getClass());

    @Autowired
    private ITradeOrderMapper iTradeOrderMapper;

    @Autowired
    private ITradeFlowMapper iTradeFlowMapper;

    @Autowired
    private IProvinceMapper iProvinceMapper;

    @Autowired
    private IProductMapper iProductMapper;

    @Autowired
    private IProductSupMapper iProductSupMapper;

    @Value("${getNumber}")
    private Integer getNumber;


    @Autowired
    private OrderService orderService;

    @Autowired
    private AsyncTaskService asyncTaskService;

    @Autowired
    private ITradeLockMapper iTradeLockMapper;

    @Autowired
    private ISalePriceMapper iSalePriceMapper;

    @Autowired
    private ITradeMerchantMapper iTradeMerchantMapper;

    @Transactional
    public void getOrderToRecharge() {

        String lockKey = "GET_ORDER_LOCK";
        TradeLock tradeLock = iTradeLockMapper.selectForUpdate(lockKey);

        if (tradeLock == null) {
            return;
        }
        TradeOrder queryCondition = new TradeOrder();
        queryCondition.setOrderStatus((short) OrderStatus.TO_PROCESS);
//        拿到住订单列表 充值状态为1 待充值
        List<TradeOrder> tradeOrders = iTradeOrderMapper.selectList(queryCondition, getNumber);

        logger.info("to process orders{}", JSON.toJSONString(tradeOrders));
        for (TradeOrder tradeOrder : tradeOrders) {
            try {
                tradeOrder.setGetCount(tradeOrder.getGetCount().add(new BigDecimal(1)));
                iTradeOrderMapper.updateGetCount(tradeOrder.getOrderId());

                TradeFlow tradeFlow = iTradeFlowMapper.selectByOrderIdForUpdate((short) 1, tradeOrder.getOrderId());
                if (tradeFlow == null) {
                    logger.warn("orderId:{}, flow is null", tradeOrder.getOrderId());
                    tradeFlow = new TradeFlow();
                    tradeFlow.setChargeStatus((short) OrderStatus.TO_PROCESS);
                    tradeFlow.setOrderId(tradeOrder.getOrderId());
                    tradeFlow.setBeginTime(new Date());
                    iTradeFlowMapper.insert(tradeFlow);
                }

                String productName = null;
                if (StringUtils.equals("HF", tradeOrder.getOrderType())) {
                    String productTemplate = "省份_运营商_面值_元";
                    Province province = iProvinceMapper.selectById(tradeOrder.getProvinceId());
                    productName = productTemplate.replace("运营商", ValueConvertUtils.ispMapper.get(tradeOrder.getIspId()))
                            .replace("省份", province.getProvinceName())
                            .replace("面值", tradeOrder.getChargeMoney() + "")
                            .replace("_", "");
                    //                这边对应的值 有对应的数据库表存 直接到表里面找
                    logger.info("orderId :{} , productName is :{}", tradeOrder.getOrderId(), productName);
                }
//            商品模板    运营商_省份_产品类型_面值_流量值_包类型  商品名为 联通_海南_全国_20元_150MB_月包
                else if (StringUtils.equals("LL", tradeOrder.getOrderType())) {
                    String productTemplate = "省份_运营商_产品类型_流量值_包类型";
                    Province province = iProvinceMapper.selectById(tradeOrder.getProvinceId());
                    productName = productTemplate.replace("运营商", ValueConvertUtils.ispMapper.get(tradeOrder.getIspId()))
                            .replace("省份", province.getProvinceName())
                            .replace("产品类型", ValueConvertUtils.busTypeMapper.get(tradeOrder.getBusiType()))
                            .replace("流量值", tradeOrder.getChargeMoney() + "M")
                            .replace("包类型", ValueConvertUtils.packageMapper.get(tradeOrder.getPackageType()))
                            .replace("_", "");
                    //                这边对应的值 有对应的数据库表存 直接到表里面找
                    logger.info("orderId :{} , productName is :{}", tradeOrder.getOrderId(), productName);

                }


                Product product = new Product();
                product.setProductName(productName);
                product = iProductMapper.selectOne(product);

                if (product == null) {
                    logger.info("product not found, order fail,orderId:{}", tradeOrder.getOrderId());
                    orderService.SGPROCESS(tradeOrder, tradeFlow);
                    continue;
                }

                tradeOrder.setProduct(productName);
                iTradeOrderMapper.updateProduct(tradeOrder.getOrderId(), productName);

                //先查找商户有没有配置商品的销售价 ， 如果没有配置就找商品默认的
                TradeMerchant tradeMerchant = iTradeMerchantMapper.selectById(tradeOrder.getMerId());

                //                如果商户的类型不是1 则需要扣款。1的则是店铺类型的
                if (!StringUtils.equals(tradeMerchant.getType(), "1") && tradeOrder.getOrderCost() == null) {

                    SalePrice salePrice = iSalePriceMapper.selectByMidPid(tradeOrder.getMerId(), product.getProductId());

                    if (salePrice == null) {
                        salePrice = iSalePriceMapper.selectByMidPid("default", product.getProductId());
                    }

                    //
                    if (iTradeMerchantMapper.subBalance(tradeOrder.getMerId(), salePrice.getSalePrice()) != 1) {
                        logger.info("balance limit,{}", JSON.toJSONString(tradeOrder));
                        orderService.FAIL(tradeOrder, tradeFlow);

                        //修改订单处理状态为2（发送失败）
                        iTradeOrderMapper.updateProcessStatus(tradeOrder.getOrderId(), "商户余额不足");
                        continue;
                    }

//                    设置销售价
                    tradeOrder.setPayMoney(salePrice.getSalePrice());
                }


                if (StringUtils.isEmpty(tradeOrder.getSupId())) {
                    ProductSup productSup = new ProductSup();
                    productSup.setProductId(product.getProductId());
                    productSup.setStatus(Boolean.TRUE);
                    List<ProductSup> productSups = iProductSupMapper.selectList(productSup);

                    if (CollectionUtils.isEmpty(productSups)) {
                        logger.warn("productName:{} not sup relation", product.getProductName());
                        orderService.FAIL(tradeOrder, tradeFlow);
                        return;
                    }

                    filter(productSups,tradeOrder);
                    if (product.isPriority()) {
                        sortByPriority(productSups);
                    } else {
                        sortByWeight(productSups);
                    }

                    tradeOrder.setSupId(productSups.get(0).getSupId());
                    StringBuffer supList = new StringBuffer();
                    for (ProductSup relation : productSups) {
                        supList.append(relation.getSupId()).append("_").append(relation.getSupName()).append(",");
                    }

                    tradeOrder.setSupList(supList.toString());
                    tradeOrder.setOrderCost(productSups.get(0).getCost());
                }


                logger.info("order suplist:{},currsup:{}", tradeOrder.getSupList(), tradeOrder.getSupId());

                tradeOrder.setOrderStatus((short) OrderStatus.PROCESSING);
                iTradeOrderMapper.updateOrderSup(tradeOrder);
                iTradeOrderMapper.updateOrderState(tradeOrder);

                tradeFlow.setChargeStatus((short) OrderStatus.PROCESSING);
                iTradeFlowMapper.updateState(tradeFlow);

                tradeFlow.setSupplierId(tradeOrder.getSupId());
                tradeFlow.setSupList(tradeOrder.getSupList());
                tradeFlow.setSupId(tradeOrder.getSupId());
                iTradeFlowMapper.updateSup(tradeFlow);

                asyncTaskService.recharge(tradeOrder, tradeFlow);
                logger.info("send to sup");
            } catch (Exception e) {
                logger.info("{} error", tradeOrder.getOrderId(), e);
            }

        }
    }

    public void filter(List<ProductSup> productSups,TradeOrder tradeOrder){
        for (Iterator<ProductSup> productSupIterator = productSups.iterator();
             productSupIterator.hasNext();){
            ProductSup productSup = productSupIterator.next();
            if (productSup.getCost()!=null &&
                    tradeOrder.getChargeMoney().compareTo(productSup.getCost().longValue())<0){

                logger.info("orderId:{} chargeMoney < supId:{} productSup cost",tradeOrder.getOrderId(),productSup.getSupId());

                productSupIterator.remove();
            }
        }
    }


    public void sortByPriority(List<ProductSup> productSups) {
        Collections.sort(productSups, new Comparator<ProductSup>() {
            @Override
            public int compare(ProductSup o1, ProductSup o2) {
                if (o1.getPriority().intValue() < o2.getPriority().intValue()) {
                    return -1;
                } else if (o1.getPriority().intValue() > o2.getPriority().intValue()) {
                    return 1;
                }
                return 0;
            }
        });
    }

    public void sortByWeight(List<ProductSup> productSups) {
        Collections.sort(productSups, new Comparator<ProductSup>() {
            @Override
            public int compare(ProductSup o1, ProductSup o2) {
                if (o1.getWeight().intValue() < o2.getWeight().intValue()) {
                    return -1;
                } else if (o1.getWeight().intValue() > o2.getWeight().intValue()) {
                    return 1;
                }
                return 0;
            }
        });
    }
}
